package com.first.core.util;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.first.core.Constants;
import com.first.core.web.filter.SecurityInterceptorFilter;
import com.first.module.acm.model.AppFunction;
import com.first.module.acm.model.AppRole;
import com.first.module.acm.model.AppUser;
import com.first.module.acm.model.FunUrl;
import com.first.module.acm.model.OnlineUser;
import com.first.module.acm.model.SystemConfig;
import com.first.module.acm.service.AppFunctionService;
import com.first.module.acm.service.FunUrlService;
import com.first.module.acm.service.SystemConfigService;

public class AppUtil implements ApplicationContextAware {
	private static Log logger = LogFactory.getLog(AppUtil.class);

	private static Map configMap = new HashMap();

	private static ServletContext servletContext = null;

	private static Map<String, OnlineUser> onlineUsers = new LinkedHashMap();
	private static ApplicationContext appContext;
	private static Document lefMenuDocument = null;

	private static Document publicDocument = null;

	private static Set<String> publicMenuIds = null;

	public void setApplicationContext(ApplicationContext applicationContext)
			throws BeansException {
		appContext = applicationContext;
	}

	public static Document getLeftMenuDocument() {
		return lefMenuDocument;
	}

	public static void setLeftMenuDocument(Document doc) {
		lefMenuDocument = doc;
	}

	public static Document getPublicDocument() {
		return publicDocument;
	}

	public static void setPublicDocument(Document pubDoc) {
		publicDocument = pubDoc;
	}

	public static void setPublicMenuIds(Set<String> pubIds) {
		publicMenuIds = pubIds;
	}

	public static Object getBean(String beanId) {
		return appContext.getBean(beanId);
	}

	public static Map<String, OnlineUser> getOnlineUsers() {
		return onlineUsers;
	}

	public static void removeOnlineUser(String sessionId) {
		onlineUsers.remove(sessionId);
	}

	public static void addOnlineUser(String sessionId, AppUser user) {
		if (!onlineUsers.containsKey(sessionId)) {
			OnlineUser onlineUser = new OnlineUser();
			onlineUser.setFullname(user.getFullname());
			onlineUser.setSessionId(sessionId);
			onlineUser.setUsername(user.getUsername());
			onlineUser.setUserId(user.getUserId());
			Set<AppRole> roles = user.getRoles();
			StringBuffer roleIds = new StringBuffer(",");
			for (AppRole role : roles) {
				roleIds.append(role.getRoleId() + ",");
			}
			onlineUser.setRoleIds(roleIds.toString());
			// onlineUser.setTitle(user.getTitle());
			onlineUsers.put(sessionId, onlineUser);
		}
	}

	/**
	 * 获取当前项目绝对路径
	 * 
	 * @return
	 */
	public static String getAppAbsolutePath() {
		return servletContext.getRealPath("/");
	}

	/**
	 * 获取流程表单配置文件的绝对路径
	 * 
	 * @return
	 */
	public static String getFlowFormAbsolutePath() {
		String path = (String) configMap.get("app.flowFormPath");
		if (path == null)
			path = "/WEB-INF/FlowForm/";
		return getAppAbsolutePath() + path;
	}

	public static String getMobileFlowFlowAbsPath() {
		return getAppAbsolutePath() + "/mobile/flow/FlowForm/";
	}

	public static void reloadSecurityDataSource() {
		SecurityInterceptorFilter securityInterceptorFilter = (SecurityInterceptorFilter) getBean("securityInterceptorFilter");
		securityInterceptorFilter.loadDataSource();
	}

	public static void init(ServletContext in_servletContext) {
		servletContext = in_servletContext;

		String filePath = servletContext.getRealPath("/WEB-INF/classes/conf/");

		Properties props = new Properties();
		try {
			InputStream is = new BufferedInputStream(new FileInputStream(
					filePath + "/config.properties"));
			props.load(is);
			Iterator it = props.keySet().iterator();
			while (it.hasNext()) {
				String key = (String) it.next();
				configMap.put(key, props.get(key));
			}
		} catch (Exception ex) {
			logger.error(ex.getMessage());
		}

		reloadSysConfig();


		String xslStyle = servletContext.getRealPath("/js/menu")
				+ "/menu-left.xsl";
		Document doc = getOrignalMenuDocument();
		try {
			Document finalDoc = XmlUtil.styleDocument(doc, xslStyle);
			setLeftMenuDocument(finalDoc);
		} catch (Exception ex) {
			logger.error("menux.xml trasform has error:" + ex.getMessage());
		}

		String publicStyle = servletContext.getRealPath("/js/menu")
				+ "/menu-public.xsl";
		try {
			Document publicDoc = XmlUtil.styleDocument(doc, publicStyle);
			HashSet pubIds = new HashSet();
			Element rootEl = publicDoc.getRootElement();
			List idNodes = rootEl.selectNodes("/Menus//*");
			for (int i = 0; i < idNodes.size(); i++) {
				Element el = (Element) idNodes.get(i);
				Attribute attr = el.attribute("id");
				if (attr != null) {
					pubIds.add(attr.getValue());
				}
			}

			setPublicMenuIds(pubIds);
			setPublicDocument(publicDoc);
		} catch (Exception ex) {
			logger.error("menu.xml + menu-public.xsl transform has error:"
					+ ex.getMessage());
		}
	}

	public static Document getOrignalMenuDocument() {
		String menuFilePath = servletContext.getRealPath("/js/menu")
				+ "/menu.xml";
		Document doc = XmlUtil.load(menuFilePath);
		return doc;
	}

	public static Document getGrantMenuDocument() {
		String xslStyle = servletContext.getRealPath("/js/menu")
				+ "/menu-grant.xsl";
		Document finalDoc = null;
		try {
			finalDoc = XmlUtil
					.styleDocument(getOrignalMenuDocument(), xslStyle);
		} catch (Exception ex) {
			logger.error("menu.xml + menu-grant.xsl transform has error:"
					+ ex.getMessage());
		}
		return finalDoc;
	}

	public static Document getPublicMenuDocument() {
		return publicDocument;
	}

	public static Set<String> getPublicMenuIds() {
		return publicMenuIds;
	}

	public static void synMenu() {
		AppFunctionService appFunctionService = (AppFunctionService) getBean("appFunctionService");
		FunUrlService funUrlService = (FunUrlService) getBean("funUrlService");

		List funNodeList = getOrignalMenuDocument().getRootElement()
				.selectNodes("/Menus/Items//Item/Function");

		for (int i = 0; i < funNodeList.size(); i++) {
			Element funNode = (Element) funNodeList.get(i);

			String key = funNode.attributeValue("id");
			String name = funNode.attributeValue("text");

			AppFunction appFunction = appFunctionService.getByKey(key);

			if (appFunction == null)
				appFunction = new AppFunction(key, name);
			else {
				appFunction.setFunName(name);
			}

			List urlNodes = funNode.selectNodes("./url");

			appFunctionService.save(appFunction);

			for (int k = 0; k < urlNodes.size(); k++) {
				Node urlNode = (Node) urlNodes.get(k);
				String path = urlNode.getText();
				FunUrl fu = funUrlService.getByPathFunId(path,
						appFunction.getFunctionId());
				if (fu == null) {
					fu = new FunUrl();
					fu.setUrlPath(path);
					fu.setAppFunction(appFunction);
					funUrlService.save(fu);
				}
			}
		}
	}

	public static boolean getIsSynMenu() {
		String synMenu = (String) configMap.get("isSynMenu");

		return "true".equals(synMenu);
	}

	public static Map getSysConfig() {
		return configMap;
	}

	public static void reloadSysConfig() {
		SystemConfigService sysConfigService = (SystemConfigService) getBean("systemConfigService");
		List<SystemConfig> list = sysConfigService.getAll();
		for (SystemConfig conf : list)
			configMap.put(conf.getConfigKey(), conf.getConfigValue());
	}

	public static String getCompanyLogo() {
		String defaultLogoPath = "/images/ehuoo_logo.png";
		String path = (String) configMap.get("app.logoPath");
		if (StringUtils.isNotEmpty(path)) {
			defaultLogoPath = "/attachFiles/" + path;
		}
		return defaultLogoPath;
	}

	public static String getCompanyName() {
		String defaultName = Constants.DEFAULT_COMPANYNAME;
		String companyName = (String) configMap.get("app.companyName");
		if (StringUtils.isNotEmpty(companyName)) {
			defaultName = companyName;
		}
		return defaultName;
	}

	/**
	 * 处理js因参数中存在特殊字符而无法执行的问题
	 * 如：\
	 * @param str
	 * @return
	 */
	public static String jsEncoder(String str) {
		if (str == null || str.equals(""))
			return "";
		str = str.replace("\\", "/");
		return str;
	}
	
	public static void main(String[] args){
		
	}
}
